package com.googlecode.spruce.remote;

import java.net.InetAddress;
import java.net.UnknownHostException;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;

import com.googlecode.spruce.core.ServiceCheckPlugin;
import com.googlecode.spruce.core.ServiceCheckPluginResult;
import com.googlecode.spruce.core.ServiceCheckResult;
import com.googlecode.spruce.remote.core.ServiceCheckService;
import com.googlecode.spruce.remote.listener.ServiceCheckListener;

/**
 * A Spring-based service-check service. This service simply accepts the name of
 * a bean that should be loaded into the Spring context already. It loads that
 * bean and casts it to {@link ServiceCheckPlugin}. It then invokes the
 * ServiceCheckPlugin and returns the results.
 */
public class SpringServiceCheckService implements ServiceCheckService, ApplicationContextAware
{
    private final static Logger logger = LoggerFactory.getLogger(SpringServiceCheckService.class);

    private final String hostName;

    private ApplicationContext applicationContext;

    private ServiceCheckListener listener;

    public SpringServiceCheckService() throws UnknownHostException
    {
        this.hostName = InetAddress.getLocalHost().getHostName();
    }

    /**
     * Perform a given service check and return the results
     * 
     * @param action
     *            The name of the plugin to invoke
     * @return The result from the plugin
     */
    public ServiceCheckResult performServiceCheck(final String action)
    {

        final ServiceCheckPlugin plugin = this.applicationContext.getBean(action, ServiceCheckPlugin.class);

        if (listener != null)
        {
            listener.preServiceCheck(action);
        }

        logger.debug("Running command [" + action + "]");

        final ServiceCheckPluginResult result = plugin.execute();

        logger.debug("Result [" + action + "][" + result + "]");

        if (listener != null)
        {
            listener.postServiceCheck(action, result);
        }

        return new ServiceCheckResultAdapter(action, this.hostName, result.getValue(), result.getMessage());
    }

    public void setApplicationContext(final ApplicationContext applicationContext) throws BeansException
    {
        this.applicationContext = applicationContext;
    }

    @Override
    public void setServiceCheckListener(final ServiceCheckListener listener)
    {
        this.listener = listener;
    }

    @Override
    public ServiceCheckListener getServiceCheckListener()
    {
        return this.listener;
    }

}
